#include <winsock2.h>
#include <stdio.h>

#include "sock_lib.h"

int Startup()
{
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2,2), &wsaData) == NO_ERROR)
		return 0;
	else
	{
		printf("Error at WSAStartup()\n");
		return -1;
	}
}

void Cleanup()
{
	WSACleanup();
}

SOCKET Connect(char *hostname, char *port)
{
	SOCKET ConnectSocket;
	struct sockaddr_in clientService; 
	struct hostent *hp;
	unsigned long ip_addr;
	
  	if ((hp=gethostbyname(hostname)) == NULL)
	{
		ip_addr = inet_addr(hostname);
		hp = gethostbyaddr((char *)&ip_addr, 4, PF_INET);
	}
	memcpy(&clientService.sin_addr, hp->h_addr, hp->h_length);
	clientService.sin_family = AF_INET;
	clientService.sin_port = htons(atoi(port));

	ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (ConnectSocket == INVALID_SOCKET) 
    {
	    printf("Error at socket(): %ld\n", WSAGetLastError());
		return -1;
    }

	if (connect(ConnectSocket, (SOCKADDR*)&clientService, sizeof(clientService)) == SOCKET_ERROR) 
    {
		printf( "Failed to connect.\n" );
		return -1;
    }
	else return ConnectSocket;
}

SOCKET Monitor(char *port_number)
{
	SOCKET ServerSocket;
	struct sockaddr_in server;

	ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (ServerSocket == INVALID_SOCKET) 
    {
	    printf("Error at socket(): %ld\n", WSAGetLastError());
		return -1;
    }

	server.sin_family = AF_INET;
	server.sin_port = htons(atoi(port_number));
	server.sin_addr.s_addr = INADDR_ANY;
	if (bind(ServerSocket, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
	{
		printf("Error at bind(): %ld\n", WSAGetLastError());
		closesocket(ServerSocket);
		return -1;
	}

	if (listen(ServerSocket, 1) == SOCKET_ERROR)
	{
		printf("Error at listen(): %ld\n", WSAGetLastError());
		return -1;
	}

	return ServerSocket;
}

SOCKET Accept(SOCKET serversocket , char *clientname)
{
	SOCKET retval = SOCKET_ERROR;
	struct sockaddr_in client;
	int clientlength = sizeof(struct sockaddr);
	struct hostent *hostptr;
	
	while (retval == -1) 
	    retval = accept(serversocket, (struct sockaddr *)&client, &clientlength);
	printf("Client connected.\n");
	

	if (hostptr = gethostbyaddr((char *)&(client.sin_addr.s_addr), 4, AF_INET)) 
        memcpy(clientname, hostptr->h_name, strlen(hostptr->h_name));
	else 
        memcpy(clientname, "unknown", 7);

	return retval;
}

int Send(SOCKET destsocket, const char *buf, int length)
{
	int sentlength = 0;
	int templength;
	
	while (length > 0)
	{
		templength = send(destsocket, buf, length, 0);
		if (templength < 0)
		{
			printf("Error at send(): %ld\n", WSAGetLastError());
			return -1;
		}
		else
		{
			sentlength += templength;
			buf += templength;
			length -= templength;
		}
	}

	return sentlength;	
}

int Recv(SOCKET clientsocket, char *buf, int length)
{
	int receivedlength = 0;
	int templength;
	
	while (length > 0)
	{
		templength = recv(clientsocket, buf, length, 0);
		if (templength < 0)
		{
			printf("Error at recv(): %ld\n", WSAGetLastError());
			return -1;
		}
		else
		if (templength == 0)
			return receivedlength;
		else
		{
			receivedlength += templength;
			buf += templength;
			length -= templength;
		}
	}

	return receivedlength;	
}

